package de.szut.ita13sommerfeld.blockadventure.window;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.Random;

import de.szut.ita13sommerfeld.blockadventure.controller.Controller;
import de.szut.ita13sommerfeld.blockadventure.controller.KeyInputAction;
import de.szut.ita13sommerfeld.blockadventure.gameentities.Entity;
import de.szut.ita13sommerfeld.blockadventure.gameentities.Player;
import de.szut.ita13sommerfeld.blockadventure.level.BufferedLoader;
import de.szut.ita13sommerfeld.blockadventure.level.LevelGenerator;
import de.szut.ita13sommerfeld.blockadventure.textures.Texture;

public class Game extends Canvas implements Runnable {

	private static final long serialVersionUID = 1L;
	public static final int BUFFER = 3;
	public static int WIDTH, HEIGHT;
	private boolean running = false;
	private Thread gamethread;
	private BufferedImage level;
	
	static Window window;
	static Controller controller;
	static Random random;
	static GameCamera camera;
	LevelGenerator levelgenerator;
	static Texture textures;
	
	public static int LEVEL = 1;
	
	
	public synchronized void start() {
		if(running)
			return;
		running = true;
		gamethread = new Thread(this);
		gamethread.start();
	}
	
	private void initialize() {
		WIDTH = getWidth();
		HEIGHT = getHeight();
		textures = new Texture();
		random = new Random();
		BufferedLoader loader = new BufferedLoader();
		level = loader.loadLevel(LEVEL);
		camera = new GameCamera(0, 0, new ViewArea(0, 0));
		controller = new Controller();
		levelgenerator = new LevelGenerator(level, controller);
		levelgenerator.generateLevel();
		addKeyListener(new KeyInputAction(controller));
	}
	
	
	//Game-Loop Updating all Objects 60 Times per Second
	
	public void run() {
		requestFocus();
		initialize();
		long lastTime = System.nanoTime();
		double amountOfTicks = 60.0;
		double ns = 1000000000 / amountOfTicks;
		double delta = 0;
		long timer = System.currentTimeMillis();
		int updates = 0;
		int frames = 0;
		while(running){
			long now = System.nanoTime();
			delta += (now - lastTime) / ns;
			lastTime = now;
			while(delta >= 1){
				tick();
				updates++;
				delta--;
			}
			render();
			frames++;
					
			if(System.currentTimeMillis() - timer > 1000){
				timer += 1000;
				window.setTitle("FPS: " + frames + " TICKS: " + updates);
				frames = 0;
				updates = 0;
			}
		}
	}
	
	private void tick() {
		controller.tick();
		for(Entity entity : controller.entities) {
			if(entity instanceof Player) {
				Player player = (Player)entity;
				camera.tick(player);
			}
		}
	}
	
	private void render() {
		BufferStrategy bufferstrategy = getBufferStrategy();
		if(bufferstrategy == null) {
			createBufferStrategy(BUFFER);
			return;
		}
		
		Graphics g = bufferstrategy.getDrawGraphics();
		Graphics2D g2d = (Graphics2D)g;
	
		g.setColor(new Color(0, 242, 255));
		g.fillRect(0, 0, getWidth(), getHeight());
		g2d.translate(camera.getX(), camera.getY());
		
		controller.render(g);
		
		g2d.translate(-camera.getX(), -camera.getY()); 
		g.dispose();
		bufferstrategy.show();
		
		controller.removeEntitiesFromGame();
		controller.addEntitiesToGame();
	}
	
	public static Texture getTexturesInstance() {
		return textures;
	}
	
	public static Controller getControllerInstance() {
		return controller;
	}
	
	public static Random getRandomInstance() {
		return random;
	}
	
	public static GameCamera getGameCameraInstance() {
		return camera;
	}
	
	public static void main(String[] args) {
		window = new Window(800,600,"BlockAdventure", new Game());
		window.setVisible(true);
	}

}
